import store from '@/store'
import moment from 'moment';
import { shuffle } from 'lodash'

export function timeFix() {
  const time = new Date()
  const hour = time.getHours()
  return hour < 9 ? '早上好' : hour <= 11 ? '上午好' : hour <= 13 ? '中午好' : hour < 20 ? '下午好' : '晚上好'
}

export function welcome() {
  const arr = ['休息一会儿吧', '准备干什么呢?', '我猜你可能累了']
  const index = Math.floor(Math.random() * arr.length)
  return arr[index]
}

export function getQueryParameters() {
  const url = window.location.href;
  const search = url.split('?')[1];
  if (!search) {
    return {
    };
  }
  return JSON.parse(`{"${decodeURIComponent(search)
    .replace(/"/g, '\\"')
    .replace(/&/g, '","')
    .replace(/=/g, '":"')}"}`);
};

/**
 * 触发 window.resize
 */
export function triggerWindowResizeEvent() {
  const event = document.createEvent('HTMLEvents')
  event.initEvent('resize', true, true)
  event.eventType = 'message'
  window.dispatchEvent(event)
}

export function handleScrollHeader(callback) {
  let timer = 0

  let beforeScrollTop = window.pageYOffset
  callback = callback || function () { }
  window.addEventListener(
    'scroll',
    event => {
      clearTimeout(timer)
      timer = setTimeout(() => {
        let direction = 'up'
        const afterScrollTop = window.pageYOffset
        const delta = afterScrollTop - beforeScrollTop
        if (delta === 0) {
          return false
        }
        direction = delta > 0 ? 'down' : 'up'
        callback(direction)
        beforeScrollTop = afterScrollTop
      }, 50)
    },
    false
  )
}

export function isIE() {
  const bw = window.navigator.userAgent
  const compare = s => bw.indexOf(s) >= 0
  const ie11 = (() => 'ActiveXObject' in window)()
  return compare('MSIE') || ie11
}

/**
 * Remove loading animate
 * @param id parent element id or class
 * @param timeout
 */
export function removeLoadingAnimate(id = '', timeout = 1500) {
  if (id === '') {
    return
  }
  setTimeout(() => {
    document.body.removeChild(document.getElementById(id))
  }, timeout)
}

/**
 * 保存 Blob 文件
 * @param blob 文件流
 * @param filename 文件名
 */
export function saveBlobAs(blob, filename) {
  if (window.navigator.msSaveOrOpenBlob) {
    navigator.msSaveBlob(blob, filename)
  } else {
    const link = document.createElement('a')
    const body = document.querySelector('body')

    link.href = window.URL.createObjectURL(blob)
    link.download = filename

    // fix Firefox
    link.style.display = 'none'
    body.appendChild(link)

    link.click()
    body.removeChild(link)

    window.URL.revokeObjectURL(link.href)
  }
}

/**
 * 下载文件
 * @param {*} url
 * @param {*} name
 */
export function downloadFile(url, name = 'file') {
  const link = document.createElement('a')
  link.href = url
  link.setAttribute('download', name) // or any other extension
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}

/**
 * 下载文件流
 * @param {*} streamData
 * @param {*} name
 * @param {*} timestamp 是否需要在文件名后面自动加上时间戳
 */
export function downloadFileStream(streamData, name = 'file', timestamp = true) {
  if (timestamp) {
    const ext = name.split('.').pop()
    const realName = name.replace(/\.[^/.]+$/, '')
    const timestamp = moment(new Date()).format('YYYYMMDDHHmm')
    name = `${realName}${timestamp}.${ext}`
  }
  const url = window.URL.createObjectURL(new Blob([streamData]))
  const link = document.createElement('a')
  link.href = url
  link.setAttribute('download', name)
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}

/**
 * 一纬数组递归转树状结构
 * @param {Array} data 一纬数组
 * @param {*} id 唯一标识符
 * @param {*} pid 关联标识符
 * @param {*} collection 子节点集合标识符
 * @param {*} icon 常规图标图标
 * @param {*} extraIcon 其它节点图标
 * @param {Array} extraData 其它需要分组的子节点
 * @param {String} relationId 俩数组关联标示符
 */
export function setArrayToTree({
  data = [],
  root = 0,
  id = 'id',
  pid = 'pid',
  collection = 'children',
  icon = '',
  extraData = [],
  relationId = 'relationId',
  extraIcon = ''
}) {
  const extraNode = {}
  extraData.forEach(item => {
    // antd Tree 组件 节点图标
    if (extraIcon) item.slots = { icon: extraIcon }

    const collection = extraNode[item[relationId]] || []
    extraNode[item[relationId]] = [...collection, item]
  })

  // 递归方法
  function getNode(data, root) {
    const node = []
    let temp
    for (let i = 0; i < data.length; i++) {
      if (data[i][pid] === root) {
        const item = data[i]
        // antd Tree 组件 节点图标
        if (icon) item.slots = { icon }
        temp = getNode(data, data[i][id])
        if (temp.length > 0) {
          // 首位部门添加标记，用于禁用上移下移
          temp[0].isFirst = true;
          temp[temp.length - 1].isLast = true;
        };
        item[collection] = [...(extraNode[item[id]] || []), ...temp]
        node.push(item)
      }
    }
    return node
  }

  return getNode(data, root)
}

// 排序
export const reorder = (list, oldIndex, newIndex) => {
  const result = Array.from(list)
  const [removed] = result.splice(oldIndex, 1)
  result.splice(newIndex, 0, removed)

  return result
}

/**
 * 列表查询参数过滤
 * @param {Object} params 原始列表查询参数
 * @returns {Object} 非空查询参数
 */
export function getQueryParams(params) {
  const query = { ...params }
  for (const key in query) {
    const value = query[key]
    const type = typeof value
    let empty
    switch (type) {
      case 'string':
        empty = value && value.trim()
        break
      case 'number':
        empty = true
        break
      case 'boolean':
        empty = true
        break
      default:
        empty = false
        break
    }
    if (!empty) delete query[key]
  }

  return query
}
/**
 * 判断时间是否有包含关系 period in range or not
 * @param {*} range
 * @param {*} period
 */
export function isTimeContain(range, period) {
  const rangeFrom = range.from
  const regExp = new RegExp('^(\\d{2})')
  const rangeTo = range.to >= range.from ? range.to : range.to.replace(regExp, s => Number(s) + 24)
  const periodFrom = period.from
  const periodTo = period.to >= period.from ? period.to : period.to.replace(regExp, s => Number(s) + 24)
  let bContain = false
  if (periodFrom >= rangeFrom && periodTo <= rangeTo) {
    bContain = true
  } else {
    const periodFromNext = period.from.replace(regExp, s => Number(s) + 24)
    const periodToNext = period.to.replace(regExp, s => Number(s) + 24)
    if (periodFromNext >= rangeFrom && periodToNext <= rangeTo) {
      bContain = true
    }
  }
  return bContain
}

/**
 * 判断时间是否有交叉关系关系
 * @param {*} range
 * @param {*} period
 */
export function isTimeCross(range, period) {
  const rangeFrom = range.from
  const regExp = new RegExp('^(\\d{2})')
  const rangeTo = range.to >= range.from ? range.to : range.to.replace(regExp, s => Number(s) + 24)
  const periodFrom = period.from
  const periodTo = period.to >= period.from ? period.to : period.to.replace(regExp, s => Number(s) + 24)

  const periodFromNext = period.from.replace(regExp, s => Number(s) + 24)
  const periodToNext = period.to.replace(regExp, s => Number(s) + 24)
  let bCross = true

  if ((periodTo <= rangeFrom || periodFrom >= rangeTo) && (periodToNext <= rangeFrom || periodFromNext >= rangeTo)) {
    bCross = false
  }
  return bCross
}

/**
 * 非递归广度优先搜索树
 * @param {*} jsonTree
 * @param {*} callback
 * @param {*} key
 */
export function breadFirstTree(jsonTree, callback, key) {
  if (!jsonTree) return
  let array = []
  if (typeof jsonTree === 'object' && jsonTree.constructor === Object.prototype.constructor) {
    array.push(jsonTree)
  } else if (Array.isArray(jsonTree)) {
    array = jsonTree
  } else {
    return
  }

  let stack = []

  // 先将第一层节点放入栈
  for (let i = 0, len = array.length; i < len; i++) {
    stack.push(array[i])
  }

  let jn

  while (stack.length) {
    jn = stack.shift()

    const re = callback(jn, array)
    if (!re) {
      return false
    }
    if (re !== -1 && jn[key] && jn[key].length > 0) {
      stack = stack.concat(jn[key])
    }
  }
}

/**
 * 树结构筛选
 * 取决于当前节点是否符合条件
 */
export function treeFilterBySelf(tree, func) {
  // 使用map复制一下节点，避免修改到原树
  return tree
    .map(node => ({
      ...node
    }))
    .filter(node => {
      if (func(node)) {
        if (node.children) {
          node.children = treeFilterBySelf(node.children, func)
        }
        return true
      }
      return false
    })
}

/**
 * 根据节点id获取完整的树节点数据
 * @param tree
 * @param id
 */
export function getTreeNodeById(tree, id) {
  let treeNode = {}
  if (id) {
    breadFirstTree(
      tree,
      node => {
        if (node.id === id) {
          treeNode = node
          return false
        }
        return true
      },
      'children'
    )
  }
  return treeNode
}

/**
 * 根据节点id获取树节点数据
 * @param tree
 * @param id
 */
export function getNodeById(tree, key, id) {
  let node = {}
  if (id) {
    for (let i = 0; i < tree.length; i++) {
      if (tree[i][key] === id) {
        node = tree[i]
        break
      } else {
        if (tree[i].child) {
          node = getNodeById(tree[i].child, key, id)
        }
      }
    }
  }
  return node
}
/**
 * 获取当前页面按钮权限
 */
export function getBtnAuth(permissionId) {
  const item = store.getters.actions.filter(i => i.permissionId === permissionId)[0]
  return item.actionList || []
}

/**
 * 判断是否具有按钮权限
 */
export function hasBtnAuth(btn, permissionId) {
  permissionId = (permissionId instanceof String && [permissionId]) || permissionId
  const item = store.getters.actions.filter(i => i.permissionId === permissionId[0])
  const btnList = btn.split(',')
  let flag = false
  for (let i = 0; i < btnList.length; i++) {
    if (item.length && item[0].actionList.includes(btnList[i])) {
      flag = true
      break
    }
  }
  return flag
}

/**
 * 判断是否具有某个路由权限
 */
export function hasRouteAuth(permissionId) {
  const hasRouter = breadFirstTree(
    store.getters.addRouters,
    jn => {
      if (jn.name == permissionId) {
        return false
      }
      return true
    },
    'children'
  )
  return hasRouter === false
}

// 获取部门所有父节点
export function getParentNode(list, id) {
  const nodes = []
  let node = list.find(item => item.id === id)
  while (node) {
    nodes.unshift(node)
    node = list.find(item => item.id === node.parentId)
  }
  return nodes
}


/**
 * 生成UUID
 */

export function uuidv4() {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
    var r = (Math.random() * 16) | 0
    var v = c == 'x' ? r : (r & 0x3) | 0x8
    return v.toString(16)
  })
}

//阿拉伯数字转中文数字
export function noToChinese(num) {
  const regExp = new RegExp('^\\d*(\\.\\d*)?$')
  if (!regExp.test(num)) {
    alert('Number is wrong!')
    return 'Number is wrong!'
  }
  const AA = new Array('零', '一', '二', '三', '四', '五', '六', '七', '八', '九')
  const BB = new Array('', '十', '百', '千', '万', '亿', '点', '')
  let a = ('' + num).replace(/(^0*)/g, '').split('.'),
    k = 0,
    re = ''
  for (var i = a[0].length - 1; i >= 0; i--) {
    switch (k) {
      case 0:
        re = BB[7] + re
        break
      case 4:
        if (!new RegExp('0{4}\\d{' + (a[0].length - i - 1) + '}$').test(a[0])) re = BB[4] + re
        break
      case 8:
        re = BB[5] + re
        BB[7] = BB[5]
        k = 0
        break
    }
    if (k % 4 == 2 && a[0].charAt(i + 2) != 0 && a[0].charAt(i + 1) == 0) re = AA[0] + re
    if (a[0].charAt(i) != 0) re = AA[a[0].charAt(i)] + BB[k % 4] + re
    k++
  }
  if (a.length > 1) {
    //加上小数部分(如果有小数部分)
    re += BB[6]
    for (var i = 0; i < a[1].length; i++) re += AA[a[1].charAt(i)]
  }
  return re
}

/**
 * 格式化秒
 * @param   int     value   总秒数
 * @return  string  result  格式化后的字符串
 */
export function formatSeconds(value) {
  let theTime = parseInt(value) // 需要转换的时间秒
  let theTime1 = 0 // 分
  let theTime2 = 0 // 小时
  let theTime3 = 0 // 天
  if (theTime >= 60) {
    theTime1 = parseInt(theTime / 60)
    theTime = parseInt(theTime % 60)
    if (theTime1 >= 60) {
      theTime2 = parseInt(theTime1 / 60)
      theTime1 = parseInt(theTime1 % 60)
      if (theTime2 >= 24) {
        //大于24小时
        theTime3 = parseInt(theTime2 / 24)
        theTime2 = parseInt(theTime2 % 24)
      }
    }
  }
  let result = ''
  if (theTime > 0) {
    result = '' + parseInt(theTime) + '秒'
  }
  if (theTime1 > 0) {
    result = '' + parseInt(theTime1) + '分' + result
  }
  if (theTime2 > 0) {
    result = '' + parseInt(theTime2) + '小时' + result
  }
  if (theTime3 > 0) {
    result = '' + parseInt(theTime3) + '天' + result
  }
  return result
}

/**
 * 查找树上一个节点的所有父节点id（前提：要有parentId）
 * @param {*} tree
 * @param {*} id
 * @returns
 */
export function getParentIdsByNodeId(tree, id) {
  let temp = [];
  const forFn = function (arr, id) {
    for (let i = 0; i < arr.length; i++) {
      const item = arr[i];
      if (item.id === id) {
        temp.push(item.id);
        forFn(tree, item.parentId);
        break;
      } else {
        if (item.children) {
          forFn(item.children, id);
        }
      }
    }
  };
  forFn(tree, id);
  return temp;
}


// 判断解析字符串是否有{}嵌套
export function judgeStr(str) {
  // 不允许${}嵌套
  const strArr = str.split('')
  let n = 0
  for (let i = 0; i < strArr.length; i++) {
    if (strArr[i] === '{') {
      if (n > 0) {
        break
      }
      n++
    }
    if (strArr[i] === '}') {
      if (n < 1) {
        break
      }
      n--
    }
  }
  return n === 0
}

// JS正则表达式解析url

export function parseUri(str) {
  const regExp_parser = new RegExp('(?:^|&)([^&=]*)=?([^&]*)', 'g')
  const regExp_strict = new RegExp('^(?:([^:\\/?#]+):)?(?:\\/\\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\\/?#]*)(?::(\\d*))?))?((((?:[^?#\\/]*\\/)*)([^?#]*))(?:\\?([^#]*))?(?:#(.*))?)')
  const regExp_loose = new RegExp('^(?:(?![^:@]+:[^:@\\/]*@)([^:\\/?#.]+):)?(?:\\/\\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\\/?#]*)(?::(\\d*))?)(((\\/(?:[^?#](?![^?#\\/]*\\.[^?#\\/.]+(?:[?#]|$)))*\\/?)?([^?#\\/]*))(?:\\?([^#]*))?(?:#(.*))?)')
  if (!parseUri || !parseUri.options) {
    parseUri.options = {
      strictMode: false,
      key: ["source", "protocol", "authority", "userInfo", "user", "password", "host", "port", "relative", "path", "directory", "file", "query", "anchor"],
      q: {
        name: "queryKey",
        parser: regExp_parser
      },
      parser: {
        strict: regExp_strict,
        loose: regExp_loose
      }
    };
  }

  if (!str) {
    return '';
  }

  var o = parseUri.options,
    m = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
    uri = {},
    i = 14;

  while (i--) uri[o.key[i]] = m[i] || "";

  uri[o.q.name] = {};
  uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
    if ($1) uri[o.q.name][$1] = $2;
  });

  return uri;
}

export function randomString(len = 6, passwordRule = 'SIMPLE') {
  const enLetters = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz'
  const number = '2345678'
  const symbol = '_@#$&'
  /** **默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1，去掉了复杂的符号****/
  const maxEn = enLetters.length
  const maxNum = number.length
  const maxSym = symbol.length
  const strArr = []
  if (passwordRule === 'COMPLEX') {
    strArr[0] = enLetters.charAt(Math.floor(Math.random() * maxEn))
    strArr[1] = number.charAt(Math.floor(Math.random() * maxNum))
    strArr[2] = symbol.charAt(Math.floor(Math.random() * maxSym))
    for (let i = 3; i < len; i++) {
      const num = Math.random() * 3
      if (num < 1) {
        strArr.push(enLetters.charAt(Math.floor(Math.random() * maxEn)))
      } else if (num < 2) {
        strArr.push(number.charAt(Math.floor(Math.random() * maxNum)))
      } else {
        strArr.push(symbol.charAt(Math.floor(Math.random() * maxSym)))
      }
    }
  } else {
    strArr[0] = enLetters.charAt(Math.floor(Math.random() * maxEn))
    strArr[1] = number.charAt(Math.floor(Math.random() * maxNum))
    for (let i = 2; i < len; i++) {
      const num = Math.random() * 1
      if (num < 0.5) {
        strArr.push(enLetters.charAt(Math.floor(Math.random() * maxEn)))
      } else {
        strArr.push(number.charAt(Math.floor(Math.random() * maxNum)))
      }
    }
  }
  return shuffle(strArr).join('')
}